package edu.unc.comp410.sharedcode;


import static java.lang.System.out;
import org.apache.log4j.Logger;


/**
 * <P>
 * This is a subset of the member functions of <CODE>Object</CODE> that should
 * normally be overridden for any "standard" class that is intended for reuse.
 * Each member function is re-abstracted forcing subclasses to define their own
 * implementations and to not default to <CODE>Object's</CODE>
 * implementations. Excluded are the <CODE>Object</CODE> member functions:
 * finalize, getClass, notify, nofifyAll, and wait.
 * </P>
 * <P>
 * Note that the annotations <CODE>@Observer, @Mustator</CODE> are redundant and their function overlaps with the Javadoc
 *           annotation <CODE>@modifies</CODE> which is more specific. <CODE>@Mutator</CODE> denotes a member function that may change the object's
 *          internal state whereas <CODE>@modifies x,y,x</CODE> specifies the particular fields that are potentially
 *           changed. <CODE>@modifies none</CODE> is equivalent to <CODE>@Observer</CODE>.
 *           </P>
 * @author hedlund
 * @lastModified Dec 12, 2007
 */
public abstract class AStandardObject implements Cloneable {
	// , IStandardObject,

	private static Logger log = Logger.getLogger(AStandardObject.class);

	/**
	 * Return a deep copy of this object
	 * 
	 * @requires true
	 * @returns \return.equals( this ) && \return.getClass() == this.getClass() &&
	 *         \return != this where the final condition specifies a deep copy
	 *         rather than a shallow copy.
	 * @throws none
	 */
	@Observer
	@Override
	public abstract Object clone();

	/**
	 * Compares theObject with <CODE>this</CODE> object for equivalence
	 * 
	 * @param theObject
	 *            to be compared with this object
	 * @requires true
	 * @modifies none
	 * @effects none
	 * @returns true <==> theObject is equivalent to this object
	 * @jointContract with AStandardObject.hashCode().
	 */
	@Observer
	@Override
	public abstract boolean equals(Object theObject);

	/**
	 * Return the hash code value for this object.
	 * 
	 * @requires true
	 * @returns \return >= 0
	 * @jointContract with AStandardObject.equals: x.equals(y) => (x.hashCode() ==
	 *                y.hashCode()), or,redundantly, objects that are equivalent
	 *                must have the same hashCode.
	 */
	@Observer
	@Override
	public abstract int hashCode();

	@Observer
	public void posthashCode(Object oldObject, Object result) {
		out.println("   AStandardObject.posthashCode called");
		assert (((Integer) result) >= 0);
	}

	/**
	 * Return the String representation of this object
	 * 
	 * @requires true
	 * @returns \return != null && ValidateUtilities.checkForContent(\result)
	 */
	@Observer
	@Override
	public abstract String toString();

	@Observer
	public void posttoString(Object oldObject, Object result) {
		out.println("   AStandardObject.posttoString called");
		ValidateUtilities.checkForContent((String) result);
		assert (null != result);
	}
}
